// WismedCalTemp.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <time.h>
#include <iostream>
#include "MathTools.h"
#include "CCalTemp.h"
#include "CFastTempFit.h"
#include "CFastTempHome.h"

extern char tempsteadyflag;					//温度稳定的标志
extern float totaltempdiff, totaltempdec;
extern bool hasCalcTempFactorLast;
extern float tempFactorNum;					//温变系数（应用于计算的）
extern float realTempFactorNum;				//实时温变系数
extern float realMicroCorrectTemp;			//实时微观修正值
extern bool debugFlagUseTempFactor;			//是否用闻变系数更新温度

/*temp接口测试通过文件读取数据*/
void apiTempCheckByFile(const char* filePathIn, char* fileName) {
	char *fileNameIn = (char*)"温度_surf_env.txt";
	//char* fileNameIn = (char*)"C11C2853DCCE_24日数据.txt";

	//char *fileNameIn = (char*)"刘跃-test.txt";
	if (fileName != NULL) {
		fileNameIn = fileName;
	}

	CSavaCharData* m_pSaveData;
	char FileName[128];
	time_t curTime = time(NULL);
	struct tm* pTm = localtime(&curTime);
	sprintf(FileName, "%4d-%02d-%02d_%02d.%02d.%02d_%s_calc.txt",
		pTm->tm_year + 1900, pTm->tm_mon + 1, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, fileNameIn);
	m_pSaveData = new CSavaCharData(FileName, (char*)"w+");

	// 算法初始化调用

	bool needInit = true;	// 根据自己的需求，在需要时初始化
	int vFlag = -1;

	int dataInterval = 2;	// 数据间隔，秒

	// 打开文件
	char filePath[1024 * 5];
	if (filePathIn != NULL) {
		sprintf(filePath, "%s\\%s", filePathIn, fileNameIn);
	}
	else {
		sprintf(filePath, "E:\\MatlabData\\2024年问题反馈处理\\20241228-尹总27日佩戴家庭测温数据\\%s", fileNameIn);
		//sprintf(filePath, "E:\\MatlabData\\2024年问题反馈处理\\20241218-家庭测温数据分析\\20241221-家庭测温算法测试\\%s", fileNameIn);

		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241120-病房测温服务器监测数据分析-体温稳定性\\20241124\\2024.11.22-2024.11.24准确性长时间测试\\%s", fileNameIn);
		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241023-体温数据分析\\20241106-体温算法更新\\%s", fileNameIn);
		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241023-体温数据分析\\原始数据\\10mm胶贴样品人体测试数据\\%s", fileNameIn);

	}
	FILE* pFile = fopen(filePath, "r");
	int pointIndex = 0;
	int index = 0;

	int fast_flag = 0; // 是否快速升温，0：不进入，1：进入
	const float FastTemp_Threshold = 32.0f;
	int fast_timecnt = 0;
	const int EndOut_Stage = 0;			// 结束快速升温输出
	const int FixedOut_Stage = 1;		// 固定快速升温输出 持续3分钟
	const int ContinueOut_Stage = 2;	// 持续快速升温输出阶段 持续判断快速计算值与准确值大小
	int fase_time_start = EndOut_Stage;
	CFastTempHome fastTempHome;			// 家庭产品用快速升温算法
	bool jumpFastTemp = false;			// 是否主动退出快速升温算法
	bool isHomeTemp = true;				// true：家庭测温，false：病房测温

	if (pFile != NULL) {
		while (true) {
			int ir, red;
			double dData[8];
			//int nRet = fscanf(pFile, "%lf %lf %lf\r\n", &dData[1], &dData[2], &dData[3]); //dEcg *= 21000;
			int nRet = fscanf(pFile, "%lf %lf\r\n", &dData[1], &dData[2], &dData[3]); //dEcg *= 21000;
			double surfTemp = dData[1];
			double envTemp = dData[2];
			int dataFlag = dData[3];

			if (nRet == 2) {
				if (needInit) {
					needInit = !needInit;
					// 初始化稳定性算法
					initCache();
					// 初始化快速升温算法
					fastTempHome.init();
					// 初始化调度
					fast_flag = 0;
					fast_timecnt = 0;
					jumpFastTemp = false;
					fase_time_start = EndOut_Stage;
				}
				nRet = 3;
				dataFlag = 0;
			}
			if (nRet == 3) {

				if (dataFlag == 1) {
					// 初始化稳定性算法
					initCache();
					// 初始化快速升温算法
					fastTempHome.init();
					// 初始化调度
					fast_flag = 0;
					fast_timecnt = 0;
					jumpFastTemp = false;
					fase_time_start = EndOut_Stage;
				}

				if (index == 109) {
					puts("find break");
				}

				// 稳定性算法
				float realTemp = CalTemp(surfTemp, envTemp, dataInterval);
				bool susSta = suspectOpen();
				bool isSensorOff = sensorOff();
				TempBuffPoint bufPoint = getBufferCache();
				int bufLen = getBuffValidLen();
				int bufStartIndex = getBuffStartIndex();

				float showTemp = realTemp;	// 实际显示的温度，默认为稳定性算法输出
				float ai_temp = -1;
				int flag_error = -1;
				int flag_stage = -1;
				float ai_ref_temp = 0;
				float tempini_check = 0;
				int fast_sta = 0;
				// 整体调度流程
				if (!jumpFastTemp) {
					// 快速升温算法

					FastTempResult_t fastRst = fastTempHome.wendu(surfTemp, envTemp, bufPoint, bufLen, bufStartIndex, isHomeTemp ? 0 : 1);

					ai_temp = fastRst.shijiwendu;
					fast_sta = fastRst.using_fast_flag;
					ai_ref_temp = fastRst.chushiwendu_tb;	// 快速升温判定的初始温度
					bool fastTempIsStable = fastRst.flat_wendingxing == 1;	// 快速升温判定温度稳定
					flag_error = fastRst.flag_error;
					flag_stage = fastRst.stage;
					tempini_check = fastRst.last_tempini_check;
					if ((ai_ref_temp <= FastTemp_Threshold) && (fast_sta == 1) && (fast_flag == 0))//启动快速升温算法输出
					{
						fast_flag = 1;
						fast_timecnt = 0;
						fase_time_start = FixedOut_Stage;
					}
					else if ((ai_ref_temp > FastTemp_Threshold) && (fast_sta == 1)) {
						// 虽然内部认定可以进入快速升温，但是初始温度高于30摄氏度，暂时不引用，防止预测温度偏差过大
						jumpFastTemp = true;
					}
					else if (surfTemp > FastTemp_Threshold && fast_sta == 0) {
						// 体表温度已经高于30摄氏度，依然没有进入快速升温，跳出快速升温
						jumpFastTemp = true;
					}
					switch (fase_time_start)
					{
					case FixedOut_Stage:
						if (fast_timecnt < 90)//3分钟 2s*90
							fast_timecnt++;
						else
						{
							fase_time_start = ContinueOut_Stage;
							fast_timecnt = 0;
						}
						// **调整，在快速升温计时阶段，如果初始温度发生变化，重置3分钟计时时间** //
						if (tempini_check == 1)
						{
							fast_timecnt = 0;
						}
						// **调整结束** //
						if (flag_error == 1)
						{ 
							showTemp = ai_temp;
							// 在快速升温预测出结果前发生异常，初始化一次，从头再来
							fastTempHome.init();
							// 初始化调度
							fast_flag = 0;
							fast_timecnt = 0;
							jumpFastTemp = false;
							fase_time_start = EndOut_Stage;
						} 
						else if (flag_error == 2)
						{
							showTemp = realTemp;
							jumpFastTemp = true;
						}
						break;
					case ContinueOut_Stage:
						if ((fabs(ai_temp - realTemp) < 0.3) || fastTempIsStable)//相差在0.3度以内
						{
							fase_time_start = EndOut_Stage;
							jumpFastTemp = true;
						}
						if (flag_error != 0)
						{
							showTemp = realTemp;
							jumpFastTemp = true;
						}
						break;
					default:
						break;
					}

					if (fast_flag == 1 && !jumpFastTemp) {
						//快速输出赋值
						showTemp = ai_temp;
					}
					else if (jumpFastTemp) {
						// todo 首次判断需要跳出快速升温，后面做温度切换后的过度优化

						// 显示稳定算法输出值
						showTemp = realTemp;
						// todo 初始化快速升温算法
						fastTempHome.init();
						fast_flag = 0;
					}
					else {
						// 显示稳定算法输出值
						showTemp = realTemp;
					}
				}
				else {
					fast_flag = 0;
				}

				if (isSensorOff) {
					showTemp = realTemp;
					needInit = true;
				}
				// 为快速升温算法的进入提供另一种条件（低于32摄氏度如果没触发那就触发它）
				if (surfTemp < FastTemp_Threshold && jumpFastTemp) {
					jumpFastTemp = false;
				}


				char tmpBuf[512] = { 0 };
				sprintf(tmpBuf, "%lf %lf %d %lf %d %lf %lf %d %lf %lf %lf %d %lf %lf %d\n", surfTemp, envTemp, dataFlag, realTemp, tempsteadyflag, totaltempdiff, totaltempdec, debugFlagUseTempFactor ? 1 : 0,
					tempFactorNum, realTempFactorNum, realMicroCorrectTemp, susSta ? 1 : 0, ai_temp, showTemp, fast_flag);	//
				char tmpBuf2[512] = { 0 };
				index++;
				sprintf(tmpBuf2, "%d:\t\t%lf %lf %d %lf %d %lf %lf %d %lf %lf %lf\r\n", index, surfTemp, envTemp, dataFlag, realTemp, tempsteadyflag, totaltempdiff, totaltempdec, hasCalcTempFactorLast ? 1 : 0,
					tempFactorNum, realTempFactorNum, realMicroCorrectTemp);	//
				m_pSaveData->writeData((unsigned char*)tmpBuf, strlen(tmpBuf));
				puts(tmpBuf2);
				m_pSaveData->fileFlush();
			}
			else {
				printf("文件读取结束.");
				fclose(pFile);
				break;
			}
		}
	}
	else {
		printf("文件不存在.\n");
	}
}


// 遍历目录并返回所有 .txt 文件
std::vector<std::string> ListFilesWithTxtExtension(const std::string& directory) {
	std::vector<std::string> txtFiles;
	WIN32_FIND_DATAA findFileData;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	// 目录路径添加通配符 \*.txt
	std::string directorySearchPath = directory + "\\*.txt";

	hFind = FindFirstFileA(directorySearchPath.c_str(), &findFileData);

	if (hFind == INVALID_HANDLE_VALUE) {
		std::cerr << "Error: Invalid directory or no .txt files found." << std::endl;
		return txtFiles;
	}

	do {
		// 检查是否为目录，如果不是则加入结果
		if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
			txtFiles.push_back(findFileData.cFileName);
			// 完整目录为
			std::string fullPath = directory + "\\" + findFileData.cFileName;
			std::cout << fullPath << std::endl;
			printf("完整路径：%s\r\n", fullPath.data());
			apiTempCheckByFile(directory.data(), findFileData.cFileName);
		}
	} while (FindNextFileA(hFind, &findFileData) != 0);

	// 关闭句柄
	FindClose(hFind);

	return txtFiles;
}


/*temp快速升温通过文件读取数据*/
void apiFastTempFitByFile(const char* filePathIn, char* fileName) {
	//char *fileNameIn = (char*)"all.txt";
	char* fileNameIn = (char*)"14_surftemp.txt";

	//char *fileNameIn = (char*)"刘跃-test.txt";
	if (fileName != NULL) {
		fileNameIn = fileName;
	}

	CSavaCharData* m_pSaveData;
	char FileName[128];
	time_t curTime = time(NULL);
	struct tm* pTm = localtime(&curTime);
	sprintf(FileName, "%4d-%02d-%02d_%02d.%02d.%02d_%s_fast_temp_calc.txt",
		pTm->tm_year + 1900, pTm->tm_mon + 1, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, fileNameIn);
	m_pSaveData = new CSavaCharData(FileName, (char*)"w+");

	// 算法初始化调用
	CFastTempFit fastTempFit;

	bool needInit = true;	// 根据自己的需求，在需要时初始化
	int vFlag = -1;

	int dataInterval = 2;	// 数据间隔，秒

	// 打开文件
	char filePath[1024 * 5];
	if (filePathIn != NULL) {
		sprintf(filePath, "%s\\%s", filePathIn, fileNameIn);
	}
	else {
		sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241118-快速升温算法—尹(20241118)\\20241118-快速升温算法—尹\\11组稳定体温数据\\包含快速升温过程\\%s", fileNameIn);
		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241023-体温数据分析\\20241106-体温算法更新\\%s", fileNameIn);
		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241023-体温数据分析\\原始数据\\10mm胶贴样品人体测试数据\\%s", fileNameIn);

	}
	FILE* pFile = fopen(filePath, "r");
	int pointIndex = 0;
	int index = 0;
	float tempData[10000] = { 0 };
	float envTempData[10000] = { 0 };
	int tempDataT[10000] = { 0 };
	int tempDataIndex = 0;

	if (pFile != NULL) {
		while (true) {
			double dData[8];
			int nRet = fscanf(pFile, "%lf %lf\r\n", &dData[1], &dData[2]); //dEcg *= 21000;

			double surfTemp = dData[1];
			if (nRet == 2) {
				if (tempDataIndex > sizeof(tempData)) {
					printf("数据超过缓冲长度%d，后面不再读取！\r\n", sizeof(tempData));
					break;
				}
				tempData[tempDataIndex] = dData[1];
				envTempData[tempDataIndex] = dData[2];
				tempDataT[tempDataIndex] = tempDataIndex * 2;
				tempDataIndex++;
				//char tmpBuf[512] = { 0 };
				//sprintf(tmpBuf, "%lf %lf %d %lf %d %lf %lf %d %lf %lf %lf\n", surfTemp, envTemp, dataFlag, realTemp, tempsteadyflag, totaltempdiff, totaltempdec, debugFlagUseTempFactor ? 1 : 0,
				//	tempFactorNum, realTempFactorNum, realMicroCorrectTemp);	//
				//char tmpBuf2[512] = { 0 };
				//index++;
				//sprintf(tmpBuf2, "%d:\t\t%lf %lf %d %lf %d %lf %lf %d %lf %lf %lf\r\n", index, surfTemp, envTemp, dataFlag, realTemp, tempsteadyflag, totaltempdiff, totaltempdec, hasCalcTempFactorLast ? 1 : 0,
				//	tempFactorNum, realTempFactorNum, realMicroCorrectTemp);	//
				//m_pSaveData->writeData((unsigned char *)tmpBuf, strlen(tmpBuf));
				//puts(tmpBuf2);
				//m_pSaveData->fileFlush();
			}
			else {
				printf("文件读取结束.");
				fclose(pFile);
				break;
			}
		}
		// 开始执行
		// 初始温度
		float T0 = tempData[0]; // 初始温度 T0
		// 参数初始化
		float T_inf = 36.0; // T_infty 初始猜测值
		float k = 0.01;     // k 初始猜测值

		printf("Initial guesses: T_infty = %.2f, k = %.4f\n", T_inf, k);

		// 获取开始时间
		clock_t start = clock();

		for (int k = 0; k < 300; k++) {
			tempData[k] = 36;
			tempDataT[k] = k * 2;
		}
		tempDataIndex = 300;

		// 需要计时的代码
		// 执行梯度下降优化
		fastTempFit.gradient_descent(T0, &T_inf, &k, tempData, tempDataT, tempDataIndex);
		//fastTempFit.gradient_descent(T0, &T_inf, &k, tempData, tempDataT, 30);

		// 获取结束时间
		clock_t end = clock();

		// 计算并输出执行时间，单位为秒
		double elapsedTime = double(end - start) / CLOCKS_PER_SEC;
		std::cout << "Execution time: " << elapsedTime << " seconds, dataLen " << tempDataIndex << "\n";

		// 输出拟合结果
		printf("Fitted parameters: T_infty = %.2f, k = %.4f, 偏差 = %lf\n", T_inf, k, T_inf - tempData[tempDataIndex - 1]);

		// 生成拟合曲线并打印
		printf("\nFitted curve:\n");
		for (int i = 0; i < tempDataIndex; i++) {
			int time = i * 2;
			float T_model = T_inf + (T0 - T_inf) * exp(-k * time);
			char tmpBuf[512] = { 0 };
			sprintf(tmpBuf, "%d %lf %lf %lf %lf %lf\n", time, tempData[i], envTempData[i], T_model, T_model - tempData[i], k);
			m_pSaveData->writeData((unsigned char*)tmpBuf, strlen(tmpBuf));
			puts(tmpBuf);
			m_pSaveData->fileFlush();
		}
		m_pSaveData->closeFile();

	}
	else {
		printf("文件不存在.\n");
	}
}

// 遍历目录并返回所有 .txt 文件
std::vector<std::string> ListFilesWithTxtExtensionForTempFit(const std::string& directory) {
	std::vector<std::string> txtFiles;
	WIN32_FIND_DATAA findFileData;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	// 目录路径添加通配符 \*.txt
	std::string directorySearchPath = directory + "\\*.txt";

	hFind = FindFirstFileA(directorySearchPath.c_str(), &findFileData);

	if (hFind == INVALID_HANDLE_VALUE) {
		std::cerr << "Error: Invalid directory or no .txt files found." << std::endl;
		return txtFiles;
	}

	do {
		// 检查是否为目录，如果不是则加入结果
		if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
			txtFiles.push_back(findFileData.cFileName);
			// 完整目录为
			std::string fullPath = directory + "\\" + findFileData.cFileName;
			std::cout << fullPath << std::endl;
			printf("完整路径：%s\r\n", fullPath.data());
			apiFastTempFitByFile(directory.data(), findFileData.cFileName);
		}
	} while (FindNextFileA(hFind, &findFileData) != 0);

	// 关闭句柄
	FindClose(hFind);

	return txtFiles;
}


int main()
{
	//printf("int %d, float %d, char %d, double %d\r\n", sizeof(int), sizeof(float), sizeof(char), sizeof(double));
	//ListFilesWithTxtExtensionForTempFit("F:\\MatlabData\\2024年问题反馈处理\\20241118-快速升温算法—尹(20241118)\\20241118-快速升温算法—尹\\11组稳定体温数据\\包含快速升温过程");
	//system("pause");

	//return 0;
	//apiFastTempFitByFile(NULL, NULL);
	//system("pause");

	apiTempCheckByFile(NULL, NULL);

	system("pause");
	std::string directory = "E:\\MatlabData\\2024年问题反馈处理\\家庭测温病房测温数据库\\家庭\\20241218-家庭测温手臂打开不同程度的数据-5组";  // 要遍历的目录
	ListFilesWithTxtExtension(directory);

	std::cout << "Hello World!\n";
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
